/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __YMODEM_H_
#define __YMODEM_H_

#include <stdint.h>


#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/

/**
  * @brief  Comm status structures definition
  */
typedef enum
{
    Ymodem_OK = 0x00,
    Ymodem_Resend,
    Ymodem_Error,
    Ymodem_Aborted,
    Ymodem_Timeout,
    Ymodem_Limit,
    Ymodem_DataRead,
    Ymodem_NoDataReadYet,
    Ymodem_PkgRead,
    Ymodem_Recving,
    Ymodem_RecvDone,
    Ymodem_CrcErr,
    Ymodem_Sending,
    Ymodem_SendDone
} YmodemStatus_t;

/* Exported constants --------------------------------------------------------*/
/* Packet structure defines */
#define PACKET_HEADER_SIZE      ((uint32_t)3)
#define PACKET_DATA_INDEX       ((uint32_t)4)
#define PACKET_START_INDEX      ((uint32_t)1)
#define PACKET_NUMBER_INDEX     ((uint32_t)2)
#define PACKET_CNUMBER_INDEX    ((uint32_t)3)
#define PACKET_TRAILER_SIZE     ((uint32_t)2)
#define PACKET_OVERHEAD_SIZE    (PACKET_HEADER_SIZE + PACKET_TRAILER_SIZE - 1)
#define PACKET_SIZE             ((uint32_t)128)
#define PACKET_1K_SIZE          ((uint32_t)1024)

/* /-------- Packet in IAP memory ------------------------------------------\
 * | 0      |  1    |  2     |  3   |  4      | ... | n+4     | n+5  | n+6  |
 * |------------------------------------------------------------------------|
 * | unused | start | number | !num | data[0] | ... | data[n] | crc0 | crc1 |
 * \------------------------------------------------------------------------/
 * the first byte is left unused for memory alignment reasons                 */

#define FILE_NAME_LENGTH        ((uint32_t)64)
#define FILE_SIZE_LENGTH        ((uint32_t)16)

#define SOH                     ((uint8_t)0x01)  /* start of 128-byte data packet */
#define STX                     ((uint8_t)0x02)  /* start of 1024-byte data packet */
#define EOT                     ((uint8_t)0x04)  /* end of transmission */
#define ACK                     ((uint8_t)0x06)  /* acknowledge */
#define NAK                     ((uint8_t)0x15)  /* negative acknowledge */
#define CA                      ((uint32_t)0x18) /* two of these in succession aborts transfer */
#define CRC16                   ((uint8_t)0x43)  /* 'C' == 0x43, request 16-bit CRC */
#define NEGATIVE_BYTE           ((uint8_t)0xFF)

#define ABORT1                  ((uint8_t)0x41)  /* 'A' == 0x41, abort by user */
#define ABORT2                  ((uint8_t)0x61)  /* 'a' == 0x61, abort by user */

#define NAK_TIMEOUT             ((uint32_t)0x100000)
#define DOWNLOAD_TIMEOUT        ((uint32_t)10000) /* One second retry delay */
#define MAX_ERRORS              ((uint32_t)5)

/**
 * @brief types of reading or writting function pointers
 * @param pdata : data pointer of buffer
 * @param len   : size of the data buffer
 * @return : the number of bytes have been read or written 
*/
typedef int32_t(*ReadIo_t)(uint8_t * pdata, int32_t len);
typedef int32_t(*WriteIo_t)(uint8_t * pdata, int32_t len);
typedef int32_t(*ReadFlash_t)(uint8_t * pdata, int32_t len);
typedef int32_t(*WriteFlash_t)(uint8_t * pdata, int32_t len);



/* Exported functions ------------------------------------------------------- */
void Ymodem_Init(ReadIo_t readIo, WriteIo_t writeIo, ReadFlash_t readFlash, WriteFlash_t writeFlash);
void Ymodem_Reset();
YmodemStatus_t Ymodem_Receive(void);
YmodemStatus_t Ymodem_Transmit(char *filename, int32_t len, uint8_t * md5);

#ifdef __cplusplus
}
#endif

#endif  /* __YMODEM_H_ */

/* EOF */
